package cn.glc.daily.life.config.propertysource;

import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.lang.Nullable;

import java.io.IOException;
import java.util.List;
import java.util.Properties;

/**
 * 拓展配置文件统一转换器
 * 原生的DefaultPropertySourceFactory配置文件仅支持properties的解析（不支持yml和yaml)
 * <p>
 * 1.这里统一处理了一下,现在如果是yml和yaml,会统一转换为properties,然后再绑定到对象上
 *
 * @author simon
 * @date 2020/11/25 10:58
 * @copyright:
 * @modifier
 * @motto a no talent, people who have to study hard
 */
public class ExtPropertySourceFactory extends DefaultPropertySourceFactory {

    private final List<String> endWithList = Lists.newArrayList(".yml", ".yaml");

    @Override
    public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
        String sourceName = MoreObjects.firstNonNull(name, resource.getResource().getFilename());
        boolean flag = endWithList.stream().filter(endWith -> sourceName.endsWith(endWith)).anyMatch(s -> true);
        //如果是yml格式配置文件就先转成properties文件格式再走父类方法就好了。
        if (flag) {
            //将YML配置转成Properties之后，再用PropertiesPropertySource绑定
            return new PropertiesPropertySource(sourceName, loadYml(resource));
        } else {
            //如果是Properties文件就默认走父类方法处理就好了。
            return super.createPropertySource(name, resource);
        }
    }

    /**
     * 将YML格式的配置转成Properties配置
     *
     * @param resource
     * @return
     */
    private Properties loadYml(EncodedResource resource) {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(resource.getResource());
        factory.afterPropertiesSet();
        return factory.getObject();
    }
}
